#ifndef U2DynLib_H
#define U2DynLib_H

#include "U2PreRequest.h"
#include "U2MemoryAllocatorConfig.h"


#if U2_PLATFORM == U2_PLATFORM_WIN32
#    define DYNLIB_HANDLE           hInstance
#    define DYNLIB_LOAD( a )        LoadLibraryEx( a, NULL, LOAD_WITH_ALTERED_SEARCH_PATH )
#    define DYNLIB_GETSYM( a, b )   GetProcAddress( a, b )
#    define DYNLIB_UNLOAD( a )      !FreeLibrary( a )

struct HINSTANCE__;
typedef struct HINSTANCE__* hInstance;

#elif U2_PLATFORM == U2_PLATFORM_LINUX || U2_PLATFORM == U2_PLATFORM_ANDROID || U2_PLATFORM == U2_PLATFORM_TEGRA2
#    define DYNLIB_HANDLE           void*
#    define DYNLIB_LOAD( a )        dlopen( a, RTLD_LAZY | RTLD_GLOBAL)
#    define DYNLIB_GETSYM( a, b )   dlsym( a, b )
#    define DYNLIB_UNLOAD( a )      dlclose( a )

#elif U2_PLATFORM == U2_PLATFORM_APPLE || U2_PLATFORM == U2_PLATFORM_APPLE_IOS
#    define DYNLIB_HANDLE           void*
#    define DYNLIB_LOAD( a )        mac_loadDylib( a )
#    define DYNLIB_GETSYM( a, b )   dlsym( a, b )
#    define DYNLIB_UNLOAD( a )      dlclose( a )

#endif


U2EG_NAMESPACE_BEGIN

class _U2Share U2DynLib : public DynLibAlloc
{
public:
    /** Default constructor - used by DynLibManager.
        @warning
            Do not call directly
    */
    U2DynLib( const U2String& name );

    /** Default destructor.
    */
    ~U2DynLib();

    /** Load the library
    */
    void load();
    /** Unload the library
    */
    void unload();
	/// Get the name of the library
	const U2String& getName(void) const { return mName; }

    /**
        Returns the address of the given symbol from the loaded library.
        @param
            strName The name of the symbol to search for
        @returns
            If the function succeeds, the returned value is a handle to
            the symbol.
        @par
            If the function fails, the returned value is <b>NULL</b>.

    */
    void* getSymbol( const U2String& strName ) const throw();

protected:
    /// Gets the last loading error
    U2String      dynlibError(void);

protected:
    U2String            mName;
    /// Handle to the loaded library.
    DYNLIB_HANDLE       mInst;
};

U2EG_NAMESPACE_END

#endif